package com.xja.interceptor;

import cn.hutool.core.util.StrUtil;
import com.xja.utils.UserContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.concurrent.TimeUnit;

import static com.xja.constant.CommonConstant.USER_LOGIN_TOKEN_PREFIX;
import static com.xja.constant.CommonConstant.USER_LOGIN_TTL;


/**
 * 用于刷新有效期的拦截器，无论任何请求的登录凭证是否有效，都不拦截
 * 如果无效直接放行
 * 如果有效就刷新有效期并将用户信息存入上下文
 * @author 蔡建国
 */
@RequiredArgsConstructor
public class UserRefreshTokenInterceptor implements HandlerInterceptor {

    private final StringRedisTemplate redisTemplate;

    // 执行controller之前执行这个方法
    @Override
    public boolean preHandle(HttpServletRequest request,
                             @NotNull HttpServletResponse response,
                             @NotNull Object handler)  {
        // 1.获取请求头中的token
        String token = request.getHeader("Authorization");
        if (StrUtil.isBlank(token)) {
            return true;
        }
        // 2.基于TOKEN获取redis中的用户id
        String key  = USER_LOGIN_TOKEN_PREFIX + token;
        String uid = redisTemplate.opsForValue().get(key);
        // 3.判断用户的登录凭证
        if (uid == null) {
            // 登录凭证无效（没携带/过期），直接放行，交给下一个拦截器处理
            return true;
        }
        // 4.登录凭证有效，刷新token的有效期并将用户id存入上下文
        UserContext.setUid(Long.valueOf(uid));
        // 5.刷新token有效期
        redisTemplate.expire(key, USER_LOGIN_TTL, TimeUnit.DAYS);
        // 6.放行
        return true;
    }

    // 返回响应之后执行这个方法
    @Override
    public void afterCompletion(@NotNull HttpServletRequest request,
                                @NotNull HttpServletResponse response,
                                @NotNull Object handler,
                                Exception ex) {
        // 移除用户
        if (UserContext.getUid() != null) {
            UserContext.removeUser();
        }
    }
}